home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!ames!mailrus!ulowell!page
- From: page@swan.ulowell.edu (Bob Page)
- Newsgroups: comp.sources.amiga
- Subject: v02i097: ls - unix-like directory lister v2.0
- Message-ID: <10673@swan.ulowell.edu>
- Date: 12 Dec 88 22:05:59 GMT
- Organization: University of Lowell, Computer Science Dept.
- Lines: 2325
- Approved: page@swan.ulowell.edu
-
- Submitted-by: nop@cup.portal.com
- Posting-number: Volume 2, Issue 97
- Archive-name: unix/ls20.1
-
- Here is a new version of Justin McCormick's "ls" program.
- Hope the net enjoys the program -- I sure do!
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # c2.a
- # ls.c
- # ls.doc
- # ls.h
- # ls.lnk
- # lssup.a
- # makefile
- # This archive created: Mon Dec 12 17:01:16 1988
- cat << \SHAR_EOF > c2.a
- *
- * C initial startup procedure under AmigaDOS
- *
- * Use the following command line to make c.o
- * asm -u -iINCLUDE: c.a
- *
- * Use the following command line to make cres.o
- * asm -u -dRESIDENT -iINCLUDE: -ocres.o c.a
-
- IDNT "c2.a"
-
- OPTION L
- LISTSYMS
- BASEREG B
- SMALLOBJ
- OPTIMON
- ADDSYM
- DEBUG
-
- * --------------------------------------------------------------------- *
- * Macros:
- * --------------------------------------------------------------------- *
- SYS MACRO *
- IFGT NARG-2
- FAIL !!!
- ENDC
- IFEQ NARG-2
- MOVE.L \2,a6
- ENDC
- JSR _LVO\1(a6)
- ENDM
-
- XLVO MACRO *
- XREF _LVO\1
- ENDM
-
- * --------------------------------------------------------------------- *
- * Equates:
- * --------------------------------------------------------------------- *
- RESIDENT EQU 1
-
- MEMF_PUBLIC EQU $1
- MEMF_CLEAR EQU $10000
- MEMFLAGS EQU MEMF_CLEAR+MEMF_PUBLIC
- AbsExecBase EQU $0004
- cli_CommandName EQU $10
- pr_CLI EQU $AC
- pr_CurrentDir EQU $98
- ThisTask EQU $114
-
- _LVOCloseLibrary EQU $FE62
- _LVOAllocMem EQU $FF3A
- _LVOFreeMem EQU $FF2E
- _LVOSetSignal EQU $FECE
- _LVOOpenLibrary EQU $FDD8
-
- XREF _DOSBase
- XREF _LinkerDB ; linker defined base value
- XREF __BSSBAS ; linker defined base of BSS
- XREF __BSSLEN ; linker defined length of BSS
-
- IFD RESIDENT
- XREF _RESLEN
- XREF _RESBASE
- XREF _NEWDATAL
- ENDC
-
- XREF __main ; Name of C program to start with.
- XREF _MemCleanup ; Free all allocated memory
- XREF ___fpinit ; initialize floating point
- XREF ___fpterm ; terminate floating point
-
- * --------------------------------------------------------------------- *
- SECTION TEXT,CODE
- * --------------------------------------------------------------------- *
- XDEF zzstart
- zzstart:
- move.l a0,a2 ; save command pointer
- move.l d0,d2 ; and command length
- lea _LinkerDB,a4 ; load base register
-
- IFND RESIDENT
- lea __BSSBAS,a3 ; get base of BSS
- moveq #0,d1
- move.l #__BSSLEN,d0 ; get length of BSS in longwords
- bra.b clr_lp ; and clear for length given
- clr_bss move.l d1,(a3)+
- clr_lp dbf d0,clr_bss
- ENDC
-
- IFD RESIDENT
- movea.l AbsExecBase,a6
-
- movem.l d0-d1/a0-a2,-(sp)
- sub.l #_RESBASE,a4
- move.l #_RESLEN,d0
- move.l #MEMFLAGS,d1
- SYS AllocMem
- tst.l d0
- beq.w abort
- move.l d0,a0
- move.l d0,a2
-
- ;a2 now has difference
- move.l d0,a1
- move.l #_NEWDATAL,d0
- ;copy data over
- cpy: move.l (a4)+,(a0)+
- subq.l #1,d0
- bne cpy
- ;a4 now points at number of relocs
- move.l (a4)+,d0
- reloc: beq.b nreloc
- move.l a1,a0
- add.l (a4)+,a0 ; a0 now has add of reloc
- add.l (a0),a2
- move.l a2,(a0)
- move.l a1,a2 ; restore offset
- subq.l #1,d0
- bra reloc
-
- nreloc: move.l a1,a4 ; set up new base register
- add.l #_RESBASE,a4
- movem.l (sp)+,d0-d1/a0-a2
- ENDC
-
- movea.l AbsExecBase,a6
- move.l a6,_SysBase(a4)
- move.l sp,__StackPtr(a4) ; Save stack ptr
- clr.l _WBenchMsg(a4)
-
- * get the address of our task
- move.l ThisTask(a6),a3
-
- *- clear any pending signals
- moveq #0,d0
- move.l #$00003000,d1
- SYS SetSignal
-
- * are we running as a son of Workbench?
- move.l pr_CurrentDir(a3),_curdir(a4)
-
- IFD WBENCH
- tst.l pr_CLI(a3)
- beq fromWorkbench
- ENDC
-
- *=======================================================================
- *====== CLI Startup Code ===============================================
- *=======================================================================
- *
- ; Entry: d2 = command length
- ; a2 = Command pointer
- fromCLI:
- move.l sp,d0 ; get top of stack
- sub.l 4(sp),d0 ; compute bottom
- add.l #128,d0 ; allow for parms overflow
- move.l d0,__base(a4) ; save for stack checking
-
- * attempt to open DOS library:
- bsr.w openDOS
-
- * find command name:
- move.l pr_CLI(a3),a0
- add.l a0,a0 ; bcpl pointer conversion
- add.l a0,a0
- move.l cli_CommandName(a0),a1
- add.l a1,a1 ; bcpl pointer conversion
- add.l a1,a1
-
- * collect parameters:
- move.l d2,d0 ; get command line length
- moveq.l #0,d1
- move.b (a1)+,d1
- move.l a1,__ProgramName(a4)
- add.l d1,d0 ; add length of command name
- addq.l #1,d0 ; allow for space after command
-
- clr.w -(sp) ; set null terminator for command line
- addq.l #1,d0 ; force to even number of bytes
- andi.w #$fffe,d0 ; (round up)
- sub.l d0,sp ; make room on stack for command line
- subq.l #2,d0
- clr.w 0(sp,d0)
-
- * copy command line onto stack
- move.l d2,d0 ; get command line length
- subq.l #1,d0
- add.l d1,d2
-
- copy_line:
- move.b 0(a2,d0.w),0(sp,d2.w) ; copy command line to stack
- subq.l #1,d2
- dbf d0,copy_line
- move.b #' ',0(sp,d2.w) ; add space between command and parms
- subq.l #1,d2
-
- copy_cmd:
- move.b 0(a1,d2.w),0(sp,d2.w) ; copy command name to stack
- dbf d2,copy_cmd
- move.l sp,a1
- move.l a1,-(sp) ; push command line address
-
- IFD WBENCH
- bra main ; call C entrypoint
- * --------------------------------------------------------------------- *
- * Workbench Startup Code
- * --------------------------------------------------------------------- *
- fromWorkbench:
- move.l TC_SPLOWER(a3),__base(a4) ; set base of stack
- moveq #127,d0
- addq.l #1,d0 ; Efficient way of getting in 128
- add.l d0,__base(a4) ; allow for parms overflow
-
- * open the DOS library:
- bsr.w openDOS
-
- * we are now set up. wait for a message from our starter
- lea pr_MsgPort(a3),a0 ; our process base
- SYS WaitPort
- lea pr_MsgPort(a3),a0 ; our process base
- SYS GetMsg
- move.l d0,_WBenchMsg(a4)
- move.l d0,-(sp)
-
- move.l d0,a2 ; get first argument
- move.l sm_ArgList(a2),d0
- beq do_cons
- move.l _DOSBase(a4),a6
- move.l d0,a0
- move.l wa_Lock(a0),d1
- move.l d1,_curdir(a4)
- SYS CurrentDir
- do_cons:
- move.l sm_ToolWindow(a2),d1 ; get the window argument
- beq do_main
- move.l #MODE_OLDFILE,d2
- SYS Open
- move.l d0,_stdin(a4)
- beq do_main
- lsl.l #2,d0
- move.l d0,a0
- move.l fh_Type(a0),pr_ConsoleTask(a3)
- do_main:
- move.l _WBenchMsg(a4),a0 ; get address of workbench message
- move.l a0,-(sp) ; push argv
- pea _NULL(a4) ; push argc
- move.l sm_ArgList(a0),a0 ; get address of arguments
- move.l wa_Name(a0),__ProgramName(a4) ; get name of program
- ENDC
-
- * --------------------------------------------------------------------- *
- * Common CLI/WBENCH code
- * --------------------------------------------------------------------- *
- main:
- IFD FLOAT
- jsr ___fpinit(pc) ; Initialize floating point
- ENDC
- jsr __main(pc) ; call C entrypoint
- moveq.l #0,d0 ; set successful status
- bra.b exit2
-
- XDEF _XCEXIT
- _XCEXIT:
- move.l 4(sp),d0 ; extract return code
-
- XDEF xXCEXIT
- xXCEXIT:
- exit2:
- IFD ERRTRAPS
- move.l d0,-(sp)
- move.l __ONEXIT(a4),d0 ; exit trap function?
- beq.b exit3
- move.l d0,a0
- jsr (a0)
- exit3:
- ENDC
-
- IFD MALLOC
- jsr _MemCleanup(pc) ; cleanup leftover memory alloc.
- ENDC
-
- movea.l AbsExecBase,a6
- move.l _DOSBase(a4),a1
- SYS CloseLibrary ; close Dos library
-
- IFD FLOAT
- jsr ___fpterm(pc) ; clean up any floating point
- ENDC
-
- IFD WBENCH
- done_1c:
- * if we ran from CLI, skip workbench cleanup:
- tst.l _WBenchMsg(a4)
- beq exitToDOS
- move.l _stdin(a4),d1
- beq.b done_4
- SYS Close
- done_4:
- * return the startup message to our parent
- * we forbid so workbench can't UnLoadSeg() us
- * before we are done:
- movea.l AbsExecBase,a6
- SYS Forbid
- move.l _WBenchMsg(a4),a1
- SYS ReplyMsg
- ENDC
-
- * this rts sends us back to DOS:
- exitToDOS:
- IFD RESIDENT
- move.l #_RESLEN,d0
- move.l a4,a1
- sub.l #_RESBASE,a1
- movea.l AbsExecBase,a6
- SYS FreeMem
- ENDC
-
- move.l (sp)+,d0
- movea.l __StackPtr(a4),sp ; restore stack ptr
-
- XDEF xchkabort
- xchkabort:
- rts
-
- IFD RESIDENT
- abort:
- movem.l (sp)+,d0-d1/a0-a2
- rts
- ENDC
-
- * --------------------------------------------------------------------- *
- noDOS:
- moveq.l #100,d0
- bra exit2
-
- * --------------------------------------------------------------------- *
- * Open the DOS library:
- * --------------------------------------------------------------------- *
- openDOS:
- lea DOSName(pc),a1
- moveq.l #0,d0
- SYS OpenLibrary
- move.l d0,_DOSBase(a4)
- beq noDOS
- rts
-
- DOSName: dc.b 'dos.library',0
-
- * --------------------------------------------------------------------- *
- section __MERGED,BSS
- * --------------------------------------------------------------------- *
-
- XDEF _NULL,_SysBase,_WBenchMsg
- XDEF _curdir,__mbase,__mnext,__msize,__tsize
- XDEF __oserr,__OSERR
- IFD FLOAT
- XDEF __FPERR
- XDEF __SIGFPE
- ENDC
- IFD ERRTRAPS
- XDEF __ONERR,__ONEXIT,__ONBREAK
- XDEF __SIGINT
- ENDC
- XDEF _stdin
- XDEF __ProgramName,__StackPtr,__base
-
- * --------------------------------------------------------------------- *
- _NULL ds.l 1 ; Huh?
- __base ds.l 1 ; base of stack
- __mbase ds.l 1 ; base of memory pool
- __mnext ds.l 1 ; next available memory location
- __msize ds.l 1 ; size of memory pool
- __tsize ds.l 1 ; total size?
- __oserr
- __OSERR ds.l 1
- IFD FLOAT
- __FPERR ds.l 1
- __SIGFPE ds.l 1
- ENDC
- IFD ERRTRAPS
- __SIGINT ds.l 1
- __ONERR ds.l 1
- __ONEXIT ds.l 1
- __ONBREAK ds.l 1
- ENDC
- _curdir ds.l 1
- _SysBase ds.l 1
- _WBenchMsg ds.l 1
- __StackPtr ds.l 1
- _stdin ds.l 1
- __ProgramName ds.l 1
-
- * --------------------------------------------------------------------- *
- END
- * --------------------------------------------------------------------- *
- SHAR_EOF
- cat << \SHAR_EOF > ls.c
- /* --------------------------------------------------------------------- *
- LS.C -- an "improved" directory listing utility to replace the
- AmigaDOS DIR and LIST commands.
-
- V1.0 August 1986 Written from scratch by Justin V. McCormick.
- V2.0 November 1988 Revised for Lattice 5.0 and made 1.3 compatible.
-
- Notice:
-
- This program is placed in the public domain with the understanding
- that the author makes no claims or guarantees with regard to its
- suitability for any given application, and that the author assumes no
- responsibility for damages incurred by its usage. Any resemblance
- of this program to any other program, either living or dead, is
- purely coincidental.
-
- Feel free to steal this code and make millions of dollars from its sale
- or commercial use, but please give credit where credit is due.
-
- Synopsis:
-
- Features adaptive columnar listing, versatile sort options,
- UNIX-style pattern matching, recursive subdirectory listing, etc!
-
- Usage:
- ls [options] [path1] [path2] ...
-
- Options:
- -? Help!
- -c Show file comment info, -c implies -l
- -d Show directory names only
- -f Show filenames only
- -l Long verbose listing showing filesizes and dates
- -n No sort, just spit them out in the order ExNext() returns
- -r Reverse sort direction
- -s Sorted by size smallest to largest
- -t Sorted by date oldest to newest
- -R Recursive descent of subdirectories
-
- All arguments are optional. Default is to give short columnar listing,
- sorted alphabetically, using the current directory. Alphabetizing is case
- insensitive.
-
- Patterns may be matched in the given names, using the UNIX-style '*'
- to wildcard any number of characters, and '?' to wildcard a single
- character. If you need to specify a pathname with spaces in it like
- "Wombat Soup", you need to put quotes around it. LS can process up to 30
- separate pathname patterns in one command line.
-
- Bugs:
-
- Redirecting the shortlist output to PRT: gives undesirable results,
- since I am using relative cursor positioning commands to format the
- screen output. I thought about using an array to store a virtual
- screen, but my primary goals were to keep the size down and display
- speed at a maxiumum. Also, LS cannot pattern match devices (like "dh*:")
- or support multiple levels of pattern matching (like "dh0:?/L*.info").
- This would involve another level of recursion and groking the Device List.
-
- Changes From 1.0 to 2.0:
-
- o Source code prototyped, linted, traced, optimized, tweaked, etc.
- o Made resident ("pseudo-pure") by linking with cres.o from LC 5.0.
- o High-volume routines recoded in assembly (lssup.a).
- o Now handles multiple paths/files on a command line, up to 30.
- o New sort flags, including no sort.
- o Enhanced wildcards, understands complex *.?*.* expressions now.
- o More efficient ExNext() performance, less ram used for recursion.
- o SIGBREAKF_CTRL_C signal (Ctrl-C) cleanly aborts at any point now.
- o Command line parser handles quoted pathnames now (LC 5.0 benefit).
- o Short listing finally auto-adjusts to new console window sizes!
- o Pen color escape codes bypassed when redirecting long output.
- o Sorting by size or date is also subsorted alphabetically now.
- o Long listing shows new 1.3 file attributes, plus comment indicator.
- o File dates are now in international format, YY-MM-DD.
- o Fixed listings with files datestamped after 99-12-31 (overflow).
- o Fixed listings with files datestamped before 78-01-01 (time < 0).
-
- * --------------------------------------------------------------------- */
-
- #include "ls.h"
-
- /* Structure used to hold file info in a linked list */
- struct FibEntry
- {
- struct FibEntry *NextFib;
- struct FibEntry *LastFib;
- struct FileInfoBlock *Fibp;
- };
-
- /* Externs from lssup.a */
- /*lint +fva2 */
- extern int __stdargs asprintf (char *, char *,...);
- /*lint -fva2 */
-
- extern __asm void SortFibs (R_D0 long, R_D1 long, R_A0 struct FibEntry *);
- extern __stdargs long iswild (char *);
- extern __stdargs long wildmatch (char *, char *);
- extern __stdargs char *FibFileDate (struct DateStamp *);
- extern __stdargs void GetWinBounds(long *, long *);
-
- /* Local CODE */
- struct FibEntry *GetDir (BPTR, struct FileInfoBlock *);
- struct FibEntry *AllocFib (void);
- void CleanUp (char *, long);
- void ColorPen2 (void);
- void CursorOff (void);
- void CursorOn (void);
- void DirIt (BPTR, char *);
- void FreeAllFibs (struct FibEntry *);
- void FreeFib (struct FibEntry *);
- void LListDir (struct FibEntry *);
- void LListEntry (struct FileInfoBlock *);
- void LongList (long *, long *, struct FibEntry *);
- void main (int, char **);
- void PagePrompt (long);
- void ResetPen (void);
- void SListDir (struct FibEntry *);
- void TestBreak (void);
- void Usage (void);
- void WCHR (char *);
- void WSTR (char *);
-
- BPTR Out = 0L;
- BPTR In = 0L;
- BPTR lockp = 0L;
- struct FileInfoBlock *GFibp = 0L;
-
- long BREAKFLAG = 0;
- long CONSOLE = 0;
- long dircount = 0;
- long DIRFILEFLAG = 0;
- long errstat = 0;
- long filecount = 0;
- long LISTALL = 0;
- long LONGLIST = 0;
- long maxnamlen = 0;
- long NOSORTFLAG = 0;
- long NOTEFLAG = 0;
- long PATHNAMED = 0;
- long REVFLAG = 0;
- long sortkey = 0;
- long WILDCARD = 0;
- long CurWinRows = 20L;
- long CurWinCols = 77L;
-
- char filename[160];
- char pattern[160];
- char workstr[160];
-
- static char Author[] = "\23333mLS 2.0\2330m by Justin V. McCormick 1988";
- static char usage[] = "\nUsage: ls [-cdflnrstR] [path1] [path2] ...\n";
-
- /* -------------------------------------------------------------------- */
- void main (argc, argv)
- int argc;
- char **argv;
- {
- struct Process *procp;
- long cnt, i;
-
- if (argc == 0) /* son of Workbench -- no go! */
- exit (0);
-
- /* Grab FileHandles for input and output to console (or redirection file) */
- In = Input ();
- Out = Output ();
- CONSOLE = (IsInteractive (Out) == 0L) ? 0L : 1L; /* Is this console output? */
-
- /* Allocate a global FileInfoBlock for ExNext() */
- if ( (GFibp = (struct FileInfoBlock *)AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR)) == 0L)
- CleanUp("No RAM?", 103L);
-
- /* Parse command line arguments <ugh> */
- cnt = 1;
- if (argc >= 2)
- {
- if (argv[1][0] == '-')
- {
- cnt++;
- for (i = strlen(argv[1]) - 1; i > 0; i--)
- {
- switch (argv[1][i])
- {
- case 'c':
- LONGLIST = 1;
- NOTEFLAG = 1;
- break;
- case 'd':
- DIRFILEFLAG |= 1;
- break;
- case 'f':
- DIRFILEFLAG |= 2;
- break;
- case 'l':
- LONGLIST = 1;
- break;
- case 'n':
- NOSORTFLAG = 1;
- break;
- case 'r':
- REVFLAG = 1;
- break;
- case 's':
- sortkey = 1;
- break;
- case 't':
- sortkey = 2;
- break;
- case 'R':
- LISTALL = 1;
- break;
- case '?':
- Usage ();
- break;
- default:
- (void) asprintf (workstr, "Unknown option \'%c\'\n", argv[1][i]);
- WSTR (workstr);
- Usage ();
- break;
- }
- }
- }
- }
-
- /* Clean up the state flags */
- if ( (argc - cnt) > 1)
- LISTALL |= 2;
-
- if (DIRFILEFLAG == 0)
- DIRFILEFLAG = 3;
-
- /* Loop through the remaining args now */
- do
- {
- PATHNAMED = 0;
- if (cnt < argc)
- {
- (void) stpcpy (pattern, argv[cnt]);
- PATHNAMED = 1;
- }
-
- if (PATHNAMED) /* If user specified a pathname */
- {
- WILDCARD = iswild (pattern); /* check for wildcards */
-
- if (WILDCARD) /* If wildcards, separate */
- { /* pattern from pathname */
- for (i = (strlen (pattern) - 1); i >= 0; i--)
- {
- if (pattern[i] == '/' || pattern[i] == ':')
- {
- (void) strncpy (filename, pattern, (UWORD) (i + 1));
- filename[i + 2] = (BYTE) 0;
- (void) stpcpy (workstr, &pattern[i + 1]);
- (void) stpcpy (pattern, workstr);
- break;
- }
- }
- /* Disallow wildcards in pathname */
- if (iswild (filename))
- CleanUp ("Sorry, can't pattern match paths", 5L);
- }
- else /* No wildcards, use filename as is */
- {
- (void) stpcpy (filename, pattern);
- }
-
- /* If the user specified a pathname, try to grab a FileLock on it */
- /* Discard trailing slash if silly Joe User put one there */
- if (filename[1] != 0 && filename[strlen (filename) - 1] == '/')
- filename[strlen (filename) - 1] = (BYTE) 0;
-
- lockp = Lock (filename, ACCESS_READ);
-
- if (!lockp) /* Can't Lock it! */
- {
- errstat = IoErr ();
- (void) strcat (filename, " not found");
- CleanUp (filename, (long)errstat);
- }
- }
- else
- {
- /*
- * If no filename was specified, steal Lock on current directory from
- * CLI process task info. We durn well better get something useful back;
- * we don't do any error checking on the stolen Lock.
- */
- procp = (struct Process *) FindTask (0L);
- lockp = procp->pr_CurrentDir;
- filename[0] = 0; /* Tell DirIt() to use current dir */
- }
-
- /* Get the directory for this path, display it */
- DirIt (lockp, filename);
-
- /* Release the lock, bump our arg counter */
- if (lockp != 0 && PATHNAMED != 0)
- UnLock (lockp);
- lockp = 0L;
- cnt++;
-
- if (cnt < argc)
- WCHR("\n");
- } while (cnt < argc && BREAKFLAG == 0);
-
- CleanUp ("", 0L);
- }
-
- /* -------------------------------------------------------------------- */
- /* Deallocate and close everything */
- /* -------------------------------------------------------------------- */
- void CleanUp (exit_msg, exit_status)
- char *exit_msg;
- long exit_status;
- {
- if (lockp && PATHNAMED)
- UnLock (lockp);
-
- if (GFibp != 0L)
- FreeMem(GFibp, (long)sizeof(struct FileInfoBlock));
-
- if (exit_status)
- {
- (void) asprintf (workstr, "ls: %s, Error #%ld\n", exit_msg, exit_status);
- WSTR (workstr);
- }
- exit ((int) exit_status);
- }
-
- /* -------------------------------------------------------------------- */
- void DirIt (lockp, dirname)
- BPTR lockp;
- char *dirname;
- {
- BPTR tlockp;
- struct FibEntry *fibheadp;
- struct FibEntry *tfibp;
- char *subdir;
- long strsize;
-
- /* Try to fill FileInfoBlock, bomb if not readable for some reason */
- if (!Examine (lockp, GFibp))
- {
- (void) asprintf (workstr, "Can't examine file or directory\n");
- WSTR (workstr);
- return;
- }
-
- /* Put directory header if this is a recursive listing */
- if (dirname[0] && LISTALL > 0)
- {
- if (CONSOLE != 0)
- (void)asprintf(workstr, "\23330;41m %s \2330m\n", dirname);
- else
- (void)asprintf(workstr, "%s\n", dirname);
- WSTR(workstr);
- }
-
- /* If this is a single file list it verbosely */
- if (GFibp->fib_EntryType < 0 && (DIRFILEFLAG & 2) != 0)
- {
- LListEntry (GFibp);
- }
- else
- {
- /* Otherwise do a directory */
- /* Allocate and initialize a FibEntry head node */
- if ( (fibheadp = GetDir (lockp, GFibp)) != 0L && BREAKFLAG == 0)
- {
- if (NOSORTFLAG == 0)
- SortFibs ((long)sortkey, REVFLAG, fibheadp);
-
- if (LONGLIST == 0)
- SListDir (fibheadp);
- else
- LListDir (fibheadp);
-
- if ( (LISTALL & 1) != 0)
- {
- tfibp = fibheadp;
- do
- {
- if (tfibp->Fibp->fib_EntryType > 0)
- {
- strsize = (strlen (dirname) + strlen (tfibp->Fibp->fib_FileName) + 2);
- subdir = (char *) AllocMem ((LONG)strsize, 0L);
- if (strlen (dirname) != 0)
- {
- (void) stpcpy (subdir, dirname);
- if (dirname[strlen (dirname) - 1] != ':')
- (void) strcat (subdir, "/");
- }
- (void) strcat (subdir, tfibp->Fibp->fib_FileName);
- tlockp = Lock (subdir, ACCESS_READ);
- if (tlockp == 0L)
- {
- WSTR (subdir);
- WSTR (" -- can't lock it!\n");
- break;
- }
- else
- {
- WCHR ("\n"); /* Put a blank line between directories */
- DirIt (tlockp, subdir);
- UnLock (tlockp);
- FreeMem (subdir, (LONG)strsize);
- }
- }
- tfibp = tfibp->NextFib;
- } while (tfibp != fibheadp && BREAKFLAG == 0);
- }
- }
- /* Clean up */
- FreeAllFibs (fibheadp);
- }
- }
-
- /* -------------------------------------------------------------------- */
- /* Allocate and fill a linked list of FileInfoBlocks */
- /* -------------------------------------------------------------------- */
- struct FibEntry *GetDir (lockp, fibp)
- BPTR lockp;
- struct FileInfoBlock *fibp;
- {
- long nextstat;
- long tempnamlen;
- struct FibEntry *tfibp;
- struct FibEntry *headfib;
-
- maxnamlen = dircount = filecount = 0L;
- headfib = 0L;
-
- do
- {
- TestBreak();
- if (BREAKFLAG != 0)
- return(headfib);
- nextstat = ExNext (lockp, fibp);
-
- if (nextstat != 0) /* We got something */
- {
- /* See if it matches our pattern */
- if (!WILDCARD || wildmatch (fibp->fib_FileName, pattern))
- {
-
- /* Bump count of files or directories */
- if (fibp->fib_EntryType > 0)
- {
- if ((DIRFILEFLAG & 1) != 0)
- dircount++;
- else
- goto ALLOCFIB;
- }
- else
- {
- if ((DIRFILEFLAG & 2) != 0)
- filecount++;
- else
- continue;
- }
-
- /* See if this is the longest filename for later use in listing */
- tempnamlen = strlen (fibp->fib_FileName);
- if (tempnamlen > maxnamlen)
- maxnamlen = tempnamlen;
-
- ALLOCFIB:
- /* Allocate another FibEntry to put the info in */
- if (headfib == 0L)
- {
- headfib = AllocFib();
- if (headfib == 0L)
- return(headfib);
- headfib->NextFib = headfib;
- headfib->LastFib = headfib;
- *(headfib->Fibp) = *(fibp);
- tfibp = headfib;
- }
- else
- {
- tfibp->NextFib = AllocFib ();
- if (tfibp->NextFib == 0L)
- return(0L);
-
- /* Copy FIB contents to next entry for ExNext to work with */
- *(tfibp->NextFib->Fibp) = *(fibp);
-
- /* Link it into the list */
- tfibp->NextFib->LastFib = tfibp;
- tfibp = tfibp->NextFib;
- tfibp->NextFib = headfib;
- }
- }
- }
- } while (nextstat);
-
- /* Return TRUE if entries found, else print message and return FALSE */
- if ( (dircount + filecount) != 0)
- {
- return (headfib);
- }
- else
- {
- if (WILDCARD == 0 && DIRFILEFLAG == 3)
- WSTR ("Volume or directory is empty.\n");
- else
- WSTR ("No match.\n");
- return (0L);
- }
- }
-
- /* -------------------------------------------------------------------- */
- /* List a FibEntry list in a compact fashion */
- /* -------------------------------------------------------------------- */
- void SListDir (fibheadp)
- struct FibEntry *fibheadp;
- {
- struct FibEntry *tfibp;
- long tabsize;
- long maxtab;
- long totrows;
- long maxwinrow;
- long colcnt;
- long rowcnt;
- long tabcnt;
- long pagecnt = 1;
-
- CursorOff (); /* Turn the cursor off since it will blink anyway */
- GetWinBounds(&CurWinCols, &CurWinRows);
-
- tfibp = fibheadp;
- tabcnt = rowcnt = colcnt = 0;
-
- tabsize = maxnamlen + 2;
- if (CurWinCols < tabsize)
- maxtab = 1;
- else
- maxtab = CurWinCols / tabsize;
- maxwinrow = CurWinRows - 3;
- if (maxwinrow <= 0)
- maxwinrow = 1;
- totrows = (dircount + filecount) / maxtab;
- if ((dircount + filecount) % maxtab != 0)
- totrows++;
-
- do
- {
- if (tfibp->Fibp->fib_EntryType > 0)
- {
- if ( (DIRFILEFLAG & 1) == 0)
- goto GETNEXTFIB;
- else
- ColorPen2 ();
- }
- if (tabcnt)
- (void) asprintf (workstr, "\233%ldC", (long)tabcnt);
- else
- workstr[0] = (BYTE) 0;
- (void) strcat (workstr, tfibp->Fibp->fib_FileName);
- (void) strcat (workstr, "\n");
- WSTR (workstr);
- if (tfibp->Fibp->fib_EntryType > 0)
- ResetPen ();
- rowcnt++;
-
- if (rowcnt == maxwinrow || rowcnt == totrows)
- {
- colcnt++; /* Start a new column */
- /* Check to see if we have used the last column up and are about to run
- * off the screen entirely. If so, give the user a chance to read it first.
- */
- if (colcnt == maxtab && rowcnt == maxwinrow && CONSOLE != 0)
- {
- if (maxwinrow > 1)
- {
- ++pagecnt; /* Advance page number count */
- PagePrompt (pagecnt); /* Print it, wait for user */
- }
- totrows -= maxwinrow;
- colcnt = tabcnt = rowcnt = 0L;
- }
- else /* Just move over one row and back up to the top */
- {
- (void) asprintf (workstr, "\233%ldA", (long)rowcnt);
- WSTR (workstr);
- tabcnt += tabsize;
- rowcnt = 0L;
- }
- }
- GETNEXTFIB:
- tfibp = tfibp->NextFib;
- } while (tfibp != fibheadp);
-
- if (totrows - rowcnt > 0) /* Cursor down till level with */
- { /* lowest line on screen */
- (void) asprintf (workstr, "\233%ldE", (long)(totrows - rowcnt));
- WSTR (workstr);
- }
- CursorOn ();
- }
-
- /* -------------------------------------------------------------------- */
- /* Reset character color to default Pen1 colors */
- /* -------------------------------------------------------------------- */
- void ResetPen ()
- {
- if (CONSOLE != 0)
- WSTR ("\2330m");
- }
-
- /* -------------------------------------------------------------------- */
- /* Turn the cursor on */
- /* -------------------------------------------------------------------- */
- void CursorOn ()
- {
- if (CONSOLE != 0)
- WSTR ("\233 p");
- }
-
- /* -------------------------------------------------------------------- */
- /* Turn the cursor off for faster text output */
- /* -------------------------------------------------------------------- */
- void CursorOff ()
- {
- if (CONSOLE != 0)
- WSTR ("\2330 p");
- }
-
- /* -------------------------------------------------------------------- */
- /* Make Pen2 <usually yellow/orange> the current charcter color */
- /* -------------------------------------------------------------------- */
- void ColorPen2 ()
- {
- if (CONSOLE != 0)
- WSTR ("\23333m");
- }
-
- /* -------------------------------------------------------------------- */
- /* Prompt the user to hit return, wait till return is hit */
- /* -------------------------------------------------------------------- */
- void PagePrompt (page)
- long page;
- {
- WSTR ("\2337m -- MORE -- Press Return: \2330m");
- (void) Read (In, workstr, 1L);
- (void) asprintf (workstr, "\233F\233K\2334;33mPage %ld:\2330m\n", (long)page);
- WSTR (workstr);
- }
-
- /* -------------------------------------------------------------------- */
- /* List a directory in a verbose informative manner */
- /* -------------------------------------------------------------------- */
- void LListDir (fibheadp)
- struct FibEntry *fibheadp;
- {
- long totblocks = 0L;
- long totbytes = 0L;
-
- CursorOff ();
- LongList (&totblocks, &totbytes, fibheadp);
-
- (void) asprintf (workstr, "Dirs:%-3ld Files:%-4ld Blocks:%-5ld Bytes:%-8ld\n",
- (long)dircount, (long)filecount, totblocks, totbytes);
- WSTR (workstr);
- CursorOn ();
- }
-
- /* -------------------------------------------------------------------- */
- void LongList (totblocks, totbytes, fibheadp)
- long *totblocks, *totbytes;
- struct FibEntry *fibheadp;
- {
- struct FibEntry *tfibp;
-
- tfibp = fibheadp;
- do
- {
- LListEntry (tfibp->Fibp);
- if (tfibp->Fibp->fib_EntryType < 0)
- {
- *totblocks += tfibp->Fibp->fib_NumBlocks;
- *totbytes += tfibp->Fibp->fib_Size;
- }
- tfibp = tfibp->NextFib;
- } while (tfibp != fibheadp);
- }
-
- /* -------------------------------------------------------------------- */
- /* Verbosely list a particular FibEntry */
- /* -------------------------------------------------------------------- */
- void LListEntry (fib)
- struct FileInfoBlock *fib;
- {
- long i, pmodes;
- char *cp1;
- char entry[160];
-
- pmodes = fib->fib_Protection & 0xff;
- cp1 = stpcpy (entry, "chsparwed ");
- for (i = 0; i < 4; i++)
- {
- if ((pmodes & (1 << i)) != 0)
- entry[8 - i] = '-';
- }
- for (; i < 8; i++)
- {
- if ((pmodes & (1 << i)) == 0)
- entry[8 - i] = '-';
- }
- if (fib->fib_Comment[0] == 0)
- entry[0] = '-';
-
- cp1 = stpcpy (cp1, FibFileDate (&fib->fib_Date));
- if (fib->fib_EntryType > 0)
- {
- if ( (DIRFILEFLAG & 1) == 0)
- return;
-
- if (CONSOLE)
- cp1 = stpcpy (cp1, "\23333m");
- cp1 = stpcpy (cp1, " Directory ");
- if (CONSOLE)
- cp1 = strcat (cp1, "\2330m");
- }
- else
- (void) asprintf (&entry[27], " %4ld %8ld ", fib->fib_NumBlocks, fib->fib_Size);
- (void)strcat(entry, fib->fib_FileName);
- (void)strcat(cp1, "\n");
- WSTR (entry);
-
- if (NOTEFLAG != 0 && fib->fib_Comment[0] != 0)
- {
- if (CONSOLE)
- (void)asprintf(cp1, "\23333m/* %s */\2330m\n", fib->fib_Comment);
- else
- (void)asprintf(cp1, "/* %s */\n", fib->fib_Comment);
- WSTR (workstr);
- }
- }
-
- #ifdef NOASM
- /* -------------------------------------------------------------------- */
- /* Calculate date based on DateStamp structure, return a string pointer */
- /* -------------------------------------------------------------------- */
- char *CalcDate (fib)
- struct FileInfoBlock *fib;
- {
- static long days[12] =
- {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
- static char *months[12] =
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- char datestr[25];
- long i, mdays;
- long day, hour;
- long minute, sec;
- long ldays;
- long year;
-
- ldays = 1461L;
- year = 78L;
- day = fib->fib_Date.ds_Days;
- minute = fib->fib_Date.ds_Minute;
- sec = fib->fib_Date.ds_Tick / 50L;
- year += (day / ldays) * 4L;
- day %= ldays;
-
- while (day)
- {
- mdays = 365;
- if ((year & 3) == 0)
- mdays++;
- if (day < mdays)
- break;
- day -= mdays;
- year++;
- }
-
- for (i = 0L, day++; i < 12; i++)
- {
- mdays = days[i];
- if (i == 1 && (year & 3) == 0)
- mdays++;
- if (day <= mdays)
- break;
- day -= mdays;
- }
- hour = minute / 60;
- minute -= hour * 60;
- (void) asprintf (datestr, "%02ld-%s-%02ld %02ld:%02ld:%02ld ", day, (long)months[i], year, hour, minute, sec);
- return (datestr);
- }
- #endif
-
- /* -------------------------------------------------------------------- */
- /* Use AmigaDos to put a string on the stdout */
- /* -------------------------------------------------------------------- */
- void WSTR (tstring)
- char *tstring;
- {
- (void) Write (Out, tstring, (long) strlen (tstring));
- }
-
- /* -------------------------------------------------------------------- */
- /* Use AmigaDos to put a character on the stdout */
- /* -------------------------------------------------------------------- */
- void WCHR (ch)
- char *ch;
- {
- (void) Write (Out, ch, 1L);
- }
-
- /* -------------------------------------------------------------------- */
- /* Check to see if the user hit ^C */
- /* -------------------------------------------------------------------- */
- void TestBreak ()
- {
- unsigned long oldsig;
-
- oldsig = SetSignal (0L, SIGBREAKF_CTRL_C);
- if ( (oldsig & SIGBREAKF_CTRL_C) != 0L)
- {
- WSTR ("\2330m\233 p**BREAK\n");
- BREAKFLAG = 1;
- }
- }
-
- /* -------------------------------------------------------------------- */
- /* Explain how to use */
- /* -------------------------------------------------------------------- */
- void Usage ()
- {
- WSTR (Author);
- WSTR (usage);
- WSTR (" c > Show comments\n");
- WSTR (" d > Dirs only\n");
- WSTR (" f > Files only\n");
- WSTR (" l > Long listing\n");
- WSTR (" n > No sort\n");
- WSTR (" r > Reverse sort\n");
- WSTR (" s > Sort by size\n");
- WSTR (" t > Sort by date\n");
- WSTR (" R > Recursive listing\n");
- CleanUp ("", 0L);
- }
-
- /* -------------------------------------------------------------------- */
- /* Allocate a FibEntry structure and associated FileInfoBlock */
- /* -------------------------------------------------------------------- */
- struct FibEntry *AllocFib ()
- {
- struct FibEntry *tfibp;
-
- tfibp = (struct FibEntry *) AllocMem \
- ((long)( sizeof (struct FibEntry) + sizeof(struct FileInfoBlock) ), 0L);
- if (tfibp != 0L)
- {
- tfibp->Fibp = (struct FileInfoBlock *)((ULONG)tfibp + sizeof(struct FibEntry));
- }
- else
- BREAKFLAG = 1;
- return (tfibp);
- }
-
- /* -------------------------------------------------------------------- */
- /* Free up memory allocated to a linked list of FibEntrys */
- /* -------------------------------------------------------------------- */
- void FreeAllFibs (fibheadp)
- struct FibEntry *fibheadp;
- {
- struct FibEntry *fibp;
- struct FibEntry *tfibp;
-
- if (fibheadp != 0)
- {
- fibp = fibheadp;
- do
- {
- tfibp = fibp->NextFib;
- FreeFib (fibp);
- fibp = tfibp;
- } while (tfibp != fibheadp);
- }
- }
-
- /* -------------------------------------------------------------------- */
- /* Deallocate a single FibEntry structure */
- /* -------------------------------------------------------------------- */
- void FreeFib (fibp)
- struct FibEntry *fibp;
- {
- if (fibp != 0L)
- FreeMem (fibp, (long)(sizeof (struct FibEntry) + sizeof(struct FileInfoBlock)));
- }
-
- SHAR_EOF
- cat << \SHAR_EOF > ls.doc
-
- LS.C -- an "improved" directory listing utility to replace the
- AmigaDOS DIR and LIST commands.
-
- V1.0 August 1986 Written from scratch by Justin V. McCormick.
- V2.0 November 1988 Revised for Lattice 5.0 and made 1.3 compatible.
-
- Notice:
-
- This program is placed in the public domain with the understanding
- that the author makes no claims or guarantees with regard to its
- suitability for any given application, and that the author assumes no
- responsibility for damages incurred by its usage. Any resemblance
- of this program to any other program, either living or dead, is
- purely coincidental.
-
- Feel free to steal this code and make millions of dollars from its sale
- or commercial use, but please give credit where credit is due.
-
- Synopsis:
-
- Features adaptive columnar listing, versatile sort options,
- UNIX-style pattern matching, recursive subdirectory listing, etc!
-
- Usage:
- ls [options] [path1] [path2] ...
-
- Options:
- -? Help!
- -c Show file comment info, -c implies -l
- -d Show directory names only
- -f Show filenames only
- -l Long verbose listing showing filesizes and dates
- -n No sort, just spit them out in the order ExNext() returns
- -r Reverse sort direction
- -s Sorted by size smallest to largest
- -t Sorted by date oldest to newest
- -R Recursive descent of subdirectories
-
- All arguments are optional. Default is to give short columnar listing,
- sorted alphabetically, using the current directory. Alphabetizing is case
- insensitive.
-
- Patterns may be matched in the given names, using the UNIX-style '*'
- to wildcard any number of characters, and '?' to wildcard a single
- character. If you need to specify a pathname with spaces in it like
- "Wombat Soup", you need to put quotes around it. LS can process up to 30
- separate pathname patterns in one command line.
-
- Bugs:
-
- Redirecting the shortlist output to PRT: gives undesirable results,
- since I am using relative cursor positioning commands to format the
- screen output. I thought about using an array to store a virtual
- screen, but my primary goals were to keep the size down and display
- speed at a maxiumum. Also, LS cannot pattern match devices (like "dh*:")
- or support multiple levels of pattern matching (like "dh0:?/L*.info").
- This would involve another level of recursion and groking the Device List.
-
- Changes From 1.0 to 2.0:
-
- o Source code prototyped, linted, traced, optimized, tweaked, etc.
- o Made resident ("pseudo-pure") by linking with cres.o from LC 5.0.
- o High-volume routines recoded in assembly (lssup.a).
- o Now handles multiple paths/files on a command line, up to 30.
- o New sort flags, including no sort.
- o Enhanced wildcards, understands complex *.?*.* expressions now.
- o More efficient ExNext() performance, less ram used for recursion.
- o SIGBREAKF_CTRL_C signal (Ctrl-C) cleanly aborts at any point now.
- o Command line parser handles quoted pathnames now (LC 5.0 benefit).
- o Short listing finally auto-adjusts to new console window sizes!
- o Pen color escape codes bypassed when redirecting long output.
- o Sorting by size or date is also subsorted alphabetically now.
- o Long listing shows new 1.3 file attributes, plus comment indicator.
- o File dates are now in international format, YY-MM-DD.
- o Fixed listings with files datestamped after 99-12-31 (overflow).
- o Fixed listings with files datestamped before 78-01-01 (time < 0).
-
- Don't send me money for this one! Its a Christmas present 8-)
- However, if you find any bugs I'd like to hear about them!
-
- Justin V. McCormick
- 8330 E. Quincy Ave., C-312
- Denver, CO 80237
-
- Home: 303-290-8429
- Work: 303-825-4144
- SHAR_EOF
- cat << \SHAR_EOF > ls.h
- #include <dos.h>
- #include <libraries/dosextens.h>
-
- /*lint -save */
- /*lint -library */
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- /*lint -restore */
-
- extern int tolower (char);
-
- /* Prevent Lint from complaining about ANSI prototype extensions */
- #ifdef _lint
-
- #define __asm
- #define __stdargs
- #define R_D0
- #define R_D1
- #define R_A0
-
- #else
-
- #define R_D0 register __d0
- #define R_D1 register __d1
- #define R_A0 register __a0
-
- #endif
-
- #define MEMF_PUBLIC (1L<<0)
- #define MEMF_CHIP (1L<<1)
- #define MEMF_FAST (1L<<2)
- #define MEMF_CLEAR (1L<<16)
- SHAR_EOF
- cat << \SHAR_EOF > ls.lnk
- DEFINE @_main = @_tinymain
- DEFINE @XCEXIT = xXCEXIT
- DEFINE @chkabort = xchkabort
- DEFINE @write = xchkabort
- DEFINE @_dclose = xchkabort
- SC SD ND
- SHAR_EOF
- cat << \SHAR_EOF > lssup.a
- * --------------------------------------------------------------------- *
- * LSSUP.A - Assembly support routines for ls.c *
- * Copyright (c) 1988 by Justin V. McCormick. All Rights Reserved. *
- * --------------------------------------------------------------------- *
- IDNT "lssup.a"
-
- include "asm:inc/macros.i"
-
- ; Assembler options for CAPE
- BASEREG B
- SMALLOBJ
- OPTIMON
- ADDSYM
- DEBUG
-
- ; Equates
- fib_FileName equ $8
- fib_Size equ $7C
- fib_NumBlocks equ $80
- fib_DateStamp equ $84
-
- ds_Days equ $0
- ds_Minute equ $4
- ds_Tick equ $8
-
- _LVOAddPort equ $FFFFFE9E
- _LVOAllocMem equ $FFFFFF3A
- _LVOAllocSignal equ $FFFFFEB6
- _LVODebug equ $FFFFFF8E
- _LVOFindTask equ $FFFFFEDA
- _LVOFreeMem equ $FFFFFF2E
- _LVOFreeSignal equ $FFFFFEB0
- _LVOGetMsg equ $FFFFFE8C
- _LVOPutMsg equ $FFFFFE92
- _LVORawDoFmt equ $FFFFFDF6
- _LVORemPort equ $FFFFFE98
- _LVORead equ $FFFFFFD6
- _LVOWaitPort equ $FFFFFE80
- _LVOWrite equ $FFFFFFD0
-
- pr_ConsoleTask EQU $A4
- MEMF_CLEAR EQU $10000
- MEMF_PUBLIC EQU $1
- sp_Msg EQU $0
- sp_Pkt EQU $14
- sp_SIZEOF EQU $44
- dp_Link EQU $0
- dp_Port EQU $4
- dp_Arg1 EQU $14
- dp_Type EQU $8
- ACTION_SCREEN_MODE EQU $3E2
- LN_NAME EQU $A
- LN_PRI EQU $9
- LN_TYPE EQU $8
- MP_FLAGS EQU $E
- MP_MSGLIST EQU $14
- MP_SIGBIT EQU $F
- MP_SIGTASK EQU $10
- MP_SIZE EQU $22
- NT_MSGPORT EQU $4
- PA_SIGNAL EQU $0
-
- * External constants
- XREF _DOSBase
- XREF _Out
- XREF _In
- * --------------------------------------------------------------------- *
- SECTION lssup,CODE
-
- * ------------------------------------------------------------------------- *
- * void asprintf(wstr, formatstring, args)
- * char *wstr;
- * char *formatstring;
- * char **args;
- *
- * Synopsis: Given formatstring and args to format, formats output to wstr.
- * Similar to sprintf(), except doesn't handle floats.
- * ------------------------------------------------------------------------- *
- XDEF _asprintf
- _asprintf:
- link a5,#0
- movem.l d0-d2/a0-a3,-(sp) ;Save everything we might clobber
-
- * Call format function to convert fmtstring and args to buffer on the stack
- movea.l 12(a5),a0 ;Grab format string
- lea 16(a5),a1 ;Grab EA of arguments
- lea kput1,a2 ;Grab EA of output subroutine
- movea.l 8(a5),a3 ;Grab EA of dest workspace
- SYS RawDoFmt,4 ;Format it into workspace
-
- movem.l (sp)+,d0-d2/a0-a3 ;Restore registers
- unlk a5 ;And stack frame
- rts
-
- * ------------------------------------------------------------------------- *
- * RawDoFmt() output routine for xprintf, called for each formatted char.
- * Takes byte in d0 and puts in buffer pointed to by a3, then increments a3.
- * ------------------------------------------------------------------------- *
- XDEF kput1
- kput1:
- move.b d0,(a3)+
- rts
-
- * --------------------------------------------------------------------- *
- * void GetWinBounds(width, height)
- * long *width, *height;
- *
- * Find current console window, determine width and height
- * in terms of current font, update width and height VPARMS passed.
- * --------------------------------------------------------------------- *
- rpstr equ -32
- rpport equ -12
- packet equ -8
- conid equ -4
-
- width equ 8
- height equ 12
-
- XDEF _GetWinBounds
- _GetWinBounds:
- link a5,#-32
- movem.l d2-d4/a2,-(sp)
-
- suba.l a1,a1
- SYS FindTask,4 ;d0 = FindTask(0L), our process
- movea.l d0,a0 ;Transfer to address reg
- move.l pr_ConsoleTask(a0),conid(a5) ;Save proc->pr_ConsoleTask
-
- moveq #0,d4 ;Clear our success status register
-
- moveq #0,d0
- movea.l d0,a0
- bsr.w CreatePort
- move.l d0,rpport(a5) ;rpport = CreatePort(0L, 0L)
- beq.w gwbdone ;Oops, no signals or ram available!
- move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
- moveq #sp_SIZEOF,d0
- SYS AllocMem
- move.l d0,packet(a5) ;packet = AllocMem(sizeof(*packet),MEMF_PUBLIC|MEMF_CLEAR)
- beq.w gwbfreeport ;Oops, no ram, free up port
-
- * Okay, we got our process id, reply port, and packet
- * Now toggle the console into raw mode
- movea.l rpport(a5),a2
- movea.l d0,a1
- movea.l conid(a5),a0
- moveq #1,d0
- bsr.w SetConsoleType ;SetConsoleType(1L, conid, packet, rpport)
-
- * Request a window bounds report
- moveq #4,d3
- lea gwbrstr(a4),a0
- move.l a0,d2
- move.l _Out(a4),d1
- SYS Write,_DOSBase(a4) ;Write(Output(), "\2330 q", 4L);
- cmpi.l #$0004,d0 ;Did the console choke on it?
- bne.w gwbsetcook ;hmmm, see if we can back out gracefully
-
- * Read the report string into stack buffer
- moveq #16,d3 ;Don't let it get longer than 16 characters
- lea rpstr(a5),a0 ;Point to input string area
- move.l a0,d2
- move.l _In(a4),d1
- SYS Read ;Read(Input(), rpstr, 16L)
- move.l d0,d4 ;Save read length while we close shop
-
- * Turn the console back to cooked mode pronto to avoid cursor blink
- gwbsetcook:
- movea.l rpport(a5),a2
- movea.l packet(a5),a1
- movea.l conid(a5),a0
- moveq #0,d0
- bsr.w SetConsoleType ;SetConsoleType(0L, conid, packet, rpport)
-
- * Release resources we borrowed
- gwbfreepack:
- move.l packet(a5),d0 ;Did we allocate a packet?
- beq.b gwbfreeport ;nay, check for port to free
- movea.l d0,a1
- moveq #sp_SIZEOF,d0
- SYS FreeMem ;Else FreeMem(packet, sizeof(*packet))
-
- gwbfreeport:
- move.l rpport(a5),d0 ;if (rpport)...
- beq.w gwbdone ;nope
- bsr.w DeletePort ;Else DeletePort(rpport)
-
- * Finally, sanity check window bounds report string
- * d4 = length of report string according to Read()
- cmpi.l #9,d4 ;Less than 8 characters returned?
- ble.w gwbdone ;hmmm, phonky bounds report from DOS?
- lea rpstr(a5),a2 ;a2 = rpstr
- cmpi.b #';',4(a2) ;Matches a typical report template?
- bne.w gwbdone ;nope, got some weird junk back?
- cmpi.b #'r',-1(a2,d4.w) ;Last byte is 'r' for report?
- bne.w gwbdone ;Nope, message fubar!
-
- * Parse the height and width variables from the field now
- * Our report format looks like this in hex:
- * 9b 31 3b 31 3b y2 y1 3b x2 x1 20 72
- * Or in ascii:
- * <0x9b>1;1;20;77 r
- * Which would indicate a width of 77 cols and a height of 20 rows for
- * the current console device
- *
- * REGS: a2 points to beginning of 'r' terminated string
-
- lea 5(a2),a2 ;Point to first char of Y size
- moveq #0,d1 ;Clear out work reg
-
- * Convert ascii rows value to LONG, update host data
- move.b (a2)+,d1 ;Grab a Y
- subi.w #'0',d1 ;Less ascii offset
- cmpi.b #';',(a2) ;Any more Y digits?
- beq.b 1$ ;Nope
- mulu #10,d1 ;Else shift by 10
- add.b (a2)+,d1 ;Add least significant Y digit
- subi.b #'0',d1 ;Less ascii offset
- cmpi.b #';',(a2) ;Any more Y digits?
- beq.b 1$ ;Nope
- mulu #$000a,d1 ;Else shift by 10
- add.b (a2)+,d1 ;Add least significant Y digit
- subi.b #'0',d1 ;Less ascii offset
- ;We'll assume screen height < 999 rows
- 1$
- * Convert ascii columns value to LONG, update host data
- addq.w #1,a2 ;Move past the ';' separator
- moveq #0,d2 ;Zap work reg
- move.b (a2)+,d2 ;Grab msd of X
- cmpi.b #' ',d2 ;Premature end?
- beq.w gwbdone ;Huh, must be garbage - don't update VPARMS
- cmpi.b #';',d2 ;Also a possible error
- beq.w gwbdone
- cmpi.b #'r',d2 ;And what about this?
- beq.w gwbdone
-
- subi.b #'0',d2 ;Okay, adjust ascii offset
- cmpi.b #' ',(a2) ;Hit end of report?
- beq.b 2$ ;Yep
- mulu #$000a,d2 ;Else shift by 10
- add.b (a2)+,d2 ;Add next digit
- subi.b #'0',d2 ;Ascii adjust
- cmpi.b #' ',(a2) ;Hit end of report?
- beq.b 2$ ;Yep
- mulu #$000a,d2 ;Else shift by 10
- add.b (a2),d2 ;Add next digit
- subi.b #'0',d2 ;Ascii adjust
-
- 2$
- * Finally, update parameters by reference
- movea.l height(a5),a0 ;Grab height VPARM
- move.l d1,(a0) ;*height = d1
- movea.l width(a5),a0 ;Grab width VPARM
- move.l d2,(a0) ;*width = d2
-
- gwbdone:
- movem.l (sp)+,d2-d4/a2
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * __asm void SetConsoleType(flag, id, packet, port)
- * register __d0 long flag;
- * register __a0 struct Process *id;
- * register __a1 struct StandardPacket *packet;
- * register __a2 struct MsgPort *port;
- *
- * Flag = 1L -- Raw mode
- * = 0L -- Cooked mode
- * --------------------------------------------------------------------- *
- XDEF SetConsoleType
- SetConsoleType:
- movem.l a3/a5,-(sp)
-
- movea.l a0,a3 ;Copy process pointer
- movea.l a1,a5 ;Copy packet pointer
- lea sp_Pkt(a5),a0 ;a0 = &packet->sp_Pkt
- move.l a0,sp_Msg+LN_NAME(a5) ;p->sp_Msg.mn_Node.ln_Name = &p->sp_Pkt
- lea sp_Msg(a5),a0 ;a0 = &packet->sp_Msg
- move.l a0,sp_Pkt+dp_Link(a5) ;p->sp_Pkt.dp_Link = &p->sp_Msg
- move.l a2,sp_Pkt+dp_Port(a5) ;p->sp_Pkt.dp_Port = replyport
- move.l #ACTION_SCREEN_MODE,sp_Pkt+dp_Type(a5) ;Set function
-
- tst.w d0 ;On or Off?
- beq.w 1$
- move.l #-1,sp_Pkt+dp_Arg1(a5) ;RAW ON
- bra.b 2$
- 1$
- clr.l sp_Pkt+dp_Arg1(a5) ;RAW OFF
- 2$
- movea.l a3,a0
- movea.l a5,a1
- SYS PutMsg,4 ;PutMsg(proc, packet)
-
- movea.l a2,a0
- SYS WaitPort ;WaitPort(port)
- movea.l a2,a0
- SYS GetMsg ;(void)GetMsg(port)
-
- movem.l (sp)+,a3/a5
- rts
-
- * ------------------------------------------------------------------------- *
- * struct MsgPort *CreatePort(name, pri) (a0/d0)
- * ------------------------------------------------------------------------- *
- XDEF CreatePort
- CreatePort:
- movem.l d5/d7/a2/a5,-(sp)
-
- move.l a0,a5 ;Save Name
- move.l d0,d5 ;Save Pri
-
- * Allocate a free signal, crap out if we can't
- moveq #-1,d0
- SYS AllocSignal,4
- cmp.l #-1,d0 ;Did we get a signal?
- bne.b cpgotsig ;Yep
- moveq #0,d0 ;Otherwise return NULL
- bra.w cpdone
-
- cpgotsig:
- move.l d0,d7 ;Save our signal
-
- * Allocate memory for MsgPort
- moveq.l #MP_SIZE,d0 ;Size of MsgPort
- move.l #MEMF_PUBLIC!MEMF_CLEAR,d1 ;Type of memory
- SYS AllocMem ;Allocate it
- tst.l d0 ;Did we get it?
- bne.b cpgotport ;Yep
-
- move.l d7,d0 ;Otherwise crap out, free signal
- SYS FreeSignal
- moveq #0,d0 ;Return NULL
- bra.w cpdone
-
- cpgotport:
- move.l d0,a2 ;This is our new port!
- move.l a5,LN_NAME(a2) ;port->mp_Node.ln_Name = name
- move.b d5,LN_PRI(a2) ;port->mp_Node.ln_Pri = priority
- move.b #NT_MSGPORT,LN_TYPE(a2) ;port->mp_Node.ln_Type = NT_MSGPORT
- move.b #PA_SIGNAL,MP_FLAGS(a2) ;port->mp_Flags = PA_SIGNAL
- move.b d7,MP_SIGBIT(a2) ;port->mp_SIGBIT = sigBit
- suba.l a1,a1
- SYS FindTask
- move.l d0,MP_SIGTASK(a2) ;port->mp_SIGTASK = FindTask(0L)
-
- cmpa.l #0,a5 ;Is this a new name?
- beq.b cpnoname ;Nope, add it to the msg list
-
- movea.l a2,a1
- SYS AddPort ;Otherwise add this port
- move.l a2,d0 ;Return port pointer
- bra.b cpdone
-
- cpnoname:
- * Initialized New List head
- lea MP_MSGLIST(a2),a0 ;a0 = &port->mp_MsgList
- move.l a0,(a0) ;list->lh_Head = list
- addq.l #4,(a0) ;list->lh_Head += 4L
- clr.l 4(a0) ;list->lh_Tail = 0L
- move.l a0,8(a0) ;list->lh_TailPred = list
- move.l a2,d0 ;Return port pointer
-
- cpdone:
- movem.l (sp)+,d5/d7/a2/a5
- rts
-
- * ------------------------------------------------------------------------- *
- * DeletePort(port)(d0)
- * ------------------------------------------------------------------------- *
- XDEF DeletePort
- DeletePort:
- move.l a5,-(sp)
-
- move.l d0,a5
- tst.l LN_NAME(a5) ;Is there a name?
- beq.s dpnoname
-
- move.l d0,a1
- SYS RemPort,4 ;RemPort(port)
-
- dpnoname:
- move.b #$ff,LN_TYPE(a5) ;port->mp_Node.ln_Type = 0xff
- move.l #-1,MP_MSGLIST(a5) ;port->mp_MsgList.lh_Head = -1L
-
- moveq #0,d0
- move.b MP_SIGBIT(a5),d0 ;d0 = port->mp_SigBit
- SYS FreeSignal,4 ;FreeSignal(d0)
-
- moveq #MP_SIZE,d0
- move.l a5,a1
- SYS FreeMem ;FreeMem(port, sizeof(*port))
-
- move.l (sp)+,a5
- rts
-
- * ------------------------------------------------------------------------
- * char *FibFileDate(fib_date)
- * register struct DateStamp *fib_date;
- *
- * Calculate date based on DateStamp structure and return a pointer
- * to the formatted date string.
- * ------------------------------------------------------------------------
- XDEF _FibFileDate
- _FibFileDate:
- link a5,#0
- movem.l d3-d7/a4,-(sp)
-
- movea.l 8(a5),a1 ;Grab datestamp pointer
- moveq #78,d7 ;Initial year = 1978
-
- move.l (a1),d5 ;days = fib_date->ds_Days
- blt ffdbaddate ;Hey! you can't be negative! Invalid date...
-
- * Determine what year it is
- divu #1461,d5
- move.l d5,d0 ;Stash it
- ext.l d5
- lsl.l #2,d5
- add.l d5,d7 ;year += (days / 1461) * 4
-
- * Count how many months into that year
- ffdgetmo:
- swap d0 ;days %= 1461
- move.w d0,d5
-
- 1$ tst.w d5 ;Out of days yet?
- beq 3$ ;Yep, done here
-
- move.w #365,d6 ;Else month_days = 365
- move.w d7,d0 ;Grab year
- andi.w #3,d0 ;if (year & 3) == 0 Leap year?
- bne 2$ ;Nope
- addq.w #1,d6 ;Otherwise bump month_days
-
- 2$ cmp.w d6,d5 ;is day < month_days?
- blt 3$ ;yep, done here
- sub.w d6,d5 ;otherwise day -= month_days
-
- addq.l #1,d7 ; year++
- bra 1$
- 3$
-
- * Count how many days into that month of that year
- ffdgetday:
- ;for (i = 0, day++; i < 12; i++)
- moveq #0,d4 ;current month = 0
- moveq #0,d6 ;Zap hinybs
- addq.w #1,d5
- lea _dayspermonth(a4),a0
-
- 1$
- move.b 0(a0,d4.w),d6 ;month_days = dayspermonth[i]
-
- cmpi.w #1,d4 ;if (i == 1 && (year & 3) == 0)
- bne 2$
- move.w d7,d0
- andi.w #3,d0
- bne 2$
- addq.w #1,d6 ;month_days++
-
- 2$ cmp.w d6,d5 ;if (day <= month_days)
- ble 4$ ;Break out, found the right month
-
- sub.w d6,d5 ;Else, day -= month_days
-
- addq.w #1,d4 ;i++
- 3$ cmpi.w #12,d4 ;Done all months yet?
- blt 1$ ;Nope
-
- 4$
- ffdprint:
- 1$ cmpi.l #99,d7 ;while (year >= 100)
- ble 2$
- subi.l #100,d7 ;year -= 100
- bra 1$
- 2$
- ;asprintf(datestr, "%02d-%02d-%02d %02d:%02d:%02d", i + 1, day, year, hour, min, sec)
- move.l 8(a1),d0 ;sec = fib_date->ds_Tick / 50;
- divu #50,d0
- move.w d0,-(sp) ;Push secs
-
- moveq #0,d0 ;Zap reg
- move.w 6(a1),d0 ;min = fib_date->ds_Minute
- move.w d0,d1 ;Clone it
- divu #60,d0
- move.w d0,d3 ;hour = min / 60
- mulu #60,d0
- sub.w d0,d1 ;min -= hour * 60
- move.w d1,-(sp) ;Push mins
-
- move.w d3,-(sp) ;Push hours
- addq.w #1,d4 ;Push day of month (offset by 1!)
- move.w d5,-(sp) ;Push month
- move.w d4,-(sp)
- move.w d7,-(sp) ;Push year
- pea _datepat(a4) ;Push the format pattern
- pea _datestr(a4) ;Push destination buffer
- jsr _asprintf
- lea 20(sp),sp
- lea _datestr(a4),a0
- move.l a0,d0 ;return((char *)&datestr[0])
-
- ffddone:
- movem.l (sp)+,d3-d7/a4
- unlk a5
- rts
-
- ffdbaddate:
- lea _baddatestr(a4),a0 ;return (" <Invalid Date> ");
- move.l a0,d0
- bra ffddone
-
- *----------------------------------------------------------------------
- * LONG iswild(name)
- * char *name;
- *
- * Search a string for wild characters, return 1 if found
- *----------------------------------------------------------------------
- XDEF _iswild
- _iswild:
- movea.l 4(sp),a0 ;Grab string pointer
- moveq #0,d0 ;Clear out our character register
- ischk1:
- move.b (a0)+,d0 ;Grab a char
- beq iwdone ;Might be end of string?
- cmpi.b #'*',d0 ;Is it *?
- beq iswdone ;yep, is wild
- cmpi.b #'?',d0 ;Is it a qmark
- bne ischk1 ;Nope, check next character
-
- iswdone:
- moveq #1,d0
- iwdone:
- rts
-
-
- * ------------------------------------------------------------------------
- ; Compare a wild card name with a normal name
- ; LONG wildmatch (name, wild)
- ; char *name, *wild;
- * ------------------------------------------------------------------------
- XDEF _wildmatch
- _wildmatch:
- link a5,#-64
- movem.l d3/a2-a3,-(sp)
-
- movea.l 8(a5),a2 ;Grab name
- movea.l 12(a5),a3 ;Grab pattern
- lea -64(a5),a0 ;back[0][0]
- lea -60(a5),a1 ;back[0][1]
-
- moveq #0,d3 ;bi = 0
-
- wmloop1:
- tst.b (a2) ;End of name?
- bne wmnoteon
- tst.b (a3) ;End of pattern?
- beq wmmatched ;Yep, we matched
-
- wmnoteon:
- cmpi.b #'*',(a3) ;Is it a splat?
- bne wmnotstar ;Nope, maybe '?'
-
- cmpi.w #64,d3 ;Have we hit max expression depth?
- beq wmnomatch ;Yep, ran out of room in recursion table
-
- ;back[bi][0] = w
- move.l a3,0(a0,d3.w) ;Stash pointer to this '*' in table
-
- ;back[bi][1] = n
- move.l a2,0(a1,d3.w)
-
- addq.w #8,d3 ;++bi
- addq.w #1,a3 ;++w
- bra wmloop1 ;Check next
-
- wmgoback:
- subq.w #8,d3 ;--bi
- move.l a0,d0
- wmback1:
- tst.w d3 ;while (bi >= 0 && *back[bi][1] == '\x0')
- blt wmbacked
- movea.l 0(a1,d3.l),a0
- tst.b (a0)
- bne wmbacked
-
- subq.w #8,d3 ;--bi
- bra wmback1
-
- wmbacked:
- tst.w d3 ;if (bi < 0)
- blt wmnomatch ;return (0)
-
- movea.l d0,a0
- movea.l 0(a0,d3.w),a3 ;w = back[bi][0] + 1
- addq.w #1,a3
-
- addq.l #1,0(a1,d3.w)
- movea.l 0(a1,d3.l),a2 ;n = ++back[bi][1]
-
- addq.w #8,d3 ;++bi
- bra wmloop1
-
- wmnotstar:
- cmpi.b #'?',(a3) ;Is it '?'
- bne wmnotqmark
-
- tst.b (a2) ;Reached end of string?
- bne wmincpoint ;Nope, move on to next char
-
- tst.w d3 ;Are we at top level of expression?
- beq wmnomatch ;Yep, expression didn't match
- bra wmgoback ;Otherwise pop a level and try to match
-
- wmnotqmark:
- move.b (a2),d0 ;Grab a char from bstr
- cmpi.b #$40,d0 ;less than @ character?
- bls 1$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi 1$ ;Yep
- addi.b #$20,d0
- 1$
- move.b (a3),d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls 2$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi 2$ ;Yep
- addi.b #$20,d1
- 2$
- cmp.b d0,d1 ;*n = *w?
- beq wmincpoint ;Yep, move on past
-
- tst.w d3 ;Are we at top expression level?
- beq wmnomatch ;Yep, they didn't match
- bra wmgoback ;Nope, process next part
-
- wmincpoint:
- tst.b (a2) ;Done with name?
- beq wmnamend ;Yep
- addq.w #1,a2 ;Otherwise increment name pointer
-
- wmnamend:
- tst.b (a3) ;End of pattern?
- beq wmmatched ;Yep, we matched
- addq.w #1,a3 ;Otherwise inc wild pointer, match next char
- bra wmloop1
-
- wmmatched:
- moveq #1,d0
- bra wmdone
-
- wmnomatch:
- moveq #0,d0
-
- wmdone:
- movem.l (sp)+,d3/a2-a3
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * void SortFibs (keytype, direction, fibheadp)
- * d0 d1 a0
- * int keytype;
- * struct FibEntry *fibheadp;
- *
- * Selection sort a linked list of FibEntrys based on a keycode *
- * --------------------------------------------------------------------- *
- XDEF _SortFibs
- _SortFibs:
- link a5,#0
- movem.l d2-d4/a2-a3/a6,-(sp)
-
- move.l d0,d2 ;Save keytype
- move.l d1,d4 ;Save direction of sort
- movea.l a0,d3 ;Save fibheadp
- movea.l a0,a2 ;a2 = a0 = i
-
- sfILoop:
- cmp.l (a2),d3 ;i->NextFib != fibheadp?
- beq sfdone ;Nope, wrapped around to start
- movea.l a2,a6 ;k = i
- movea.l (a2),a3 ;j = i->NextFib
-
- sfJLoop:
- cmp.l a3,d3 ;j != fibheadp?
- beq sfJdone ;Nope compared them all, see if swapped any
- movea.l 8(a6),a0 ;a0 = k->Fibp
- movea.l 8(a3),a1 ;a1 = j->Fibp
- move.l d2,d0 ;d0 = keytype
- jsr _CompFibs ;d0 = CompFibs(keytype, k->Fibp, j->Fibp)
- tst.w d4 ;Reverse sort?
- beq 1$ ;Nope
- bchg.l #0,d0 ;Else reverse sense of return
- 1$
- tst.l d0 ;Return != 0?
- beq sfNextJ ;Nope, these two are in order
- movea.l a3,a6 ;else k = j, this is new swap
-
- sfNextJ:
- movea.l (a3),a3 ;j = j->NextFib
- bra sfJLoop ;Check bounds
-
- sfJdone:
- cmpa.l a6,a2 ;k != i, did we swap?
- beq sfNextI ;Nope, i was in correct position already
- move.l 8(a6),d0
- move.l 8(a2),8(a6)
- move.l d0,8(a2) ;Else SwapFibs (k, i)
-
- sfNextI:
- movea.l (a2),a2 ;i = i->NextFib
- bra sfILoop ;Check bounds
-
- sfdone:
- movem.l (sp)+,d2-d4/a2-a3/a6
- unlk a5
- rts
-
- * --------------------------------------------------------------------- *
- * int CompFibs (keytype, a, b)
- * d0 a0 a1
- * int keytype;
- * struct FileInfoBlock *a, *b;
- *
- * Used by SortFibs to determine precedence of Fibs.
- * --------------------------------------------------------------------- *
- XDEF _CompFibs
- _CompFibs:
- tst.w d0 ;Alphabetize?
- bne cfnalpha ;Nope
-
- * Compare lexigraphically, ignoring case differences
- cfalpha:
- lea fib_FileName(a0),a0 ;a = &Fipb->fib_FileName
- lea fib_FileName(a1),a1 ;b = &Fipb->fib_FileName
-
- ; for(; *a && tolower(*a) == tolower(*b); a++, b++);
- lccstart:
- tst.b (a0) ;Is there a char here at source?
- beq lcceostr ;Nope, fell off the end
-
- move.b (a1)+,d1 ;Grab a char from bstr
- cmpi.b #$40,d1 ;less than @ character?
- bls 1$ ;Yep
- cmpi.b #$5a,d1 ;Greater than Z?
- bhi 1$ ;Yep
- addi.b #$20,d1
- 1$
- move.b (a0)+,d0 ;Grab a char from astr
- cmpi.b #$40,d0 ;less than @ character?
- bls 2$ ;Yep
- cmpi.b #$5a,d0 ;Greater than Z?
- bhi 2$ ;Yep
- addi.b #$20,d0
- 2$
- cmp.b d0,d1 ;are they the same?
- beq lccstart ;Yep, compare next pair of chars
-
- lcceostr:
- sub.b d1,d0 ;return(tolower(*astr) - tolower(*bstr))
- bgt cftrue ; > 0?, return TRUE
- bra cffalse ;Else return FALSE
-
- cfnalpha:
- subq.w #1,d0 ;Size?
- bne cfnsize ;Nope
-
- * Compare fib_Sizes
- move.l fib_Size(a1),d0 ;d0 = bfib->fib_Size
- cmp.l fib_Size(a0),d0 ;a->fib_Size > b->fib_Size?
- blt cftrue ;Yep, return TRUE
- bgt cffalse ;<, return FALSE
- bra cfalpha ;Else it's a tie, alphabetize
-
- cfnsize:
- subq.w #1,d0 ;Time?
- bne cffalse ;Nope, an error!
-
- * Compare fib_DateStamps
- lea fib_DateStamp(a0),a0 ;a = &afib->fib_DateStamp
- lea fib_DateStamp(a1),a1 ;b = &bfib->fib_DateStamp
- move.l ds_Days(a1),d0 ;d0 = bdate->ds_Days
- cmp.l ds_Days(a0),d0 ;a->ds_Days > b->ds_Days?
- blt cftrue ;Yep, a is older
- bgt cffalse ;Else if a < b, b is older
- ;Else they are the same day, check min/tick
- move.l ds_Minute(a0),d0
- sub.l ds_Minute(a1),d0 ;d0 = amin - bmin
- muls #3000,d0 ; * 3000
- add.l ds_Tick(a0),d0
- sub.l ds_Tick(a1),d0 ; + atick - btick
- bgt cftrue ;Hey, a > b
- blt cffalse ;a < b, return false
- bra cfalpha ;Else its the same date, alphabetize
-
- cftrue:
- moveq #1,d0
- rts
- cffalse:
- moveq #0,d0
- rts
-
- * --------------------------------------------------------------------- *
- SECTION __MERGED,DATA
- * --------------------------------------------------------------------- *
- XDEF _dayspermonth
- _dayspermonth:
- dc.b 31,28,31,30,31,30,31,31,30,31,30,31
- XDEF _datepat
- _datepat:
- dc.b '%02d-%02d-%02d %02d:%02d:%02d',0
- CNOP 0,2
- XDEF _baddatestr
- _baddatestr:
- dc.b '00-00-00 00:00:00',0
- CNOP 0,2
-
- XDEF gwbrstr
- gwbrstr:
- dc.b $9b,'0 q'
-
- * --------------------------------------------------------------------- *
- SECTION __MERGED,BSS
- * --------------------------------------------------------------------- *
- XDEF _datestr
- _datestr:
- ds.b 40
-
- * --------------------------------------------------------------------- *
- END
- * --------------------------------------------------------------------- *
- SHAR_EOF
- cat << \SHAR_EOF > makefile
- # -------------------------------------------
- # LS 2.0 lmkfile by Justin V. McCormick 88/11/27
- # -------------------------------------------
- OBJS = c2.o ls.o lssup.o
- DEST = lcs
-
- ASM = casm
- ASFLAGS = -cv
- AINC = ainc:
- LC = lc
- LC1 = lc1
- LC2 = lc2
- LCFLAGS = -ccfmsu -d2 -rr -v
-
- LINK = blink
- LIBS = lib:lcr.lib
- LNMAP = F H L S X PLAIN WIDTH 84 HEIGHT 0 SWIDTH 20
-
- .a.o:
- $(ASM) -a $*.a -o$*.o -i$(AINC) $(ASFLAGS)
-
- .c.o:
- $(LC) $(LCFLAGS) $*
-
- $(DEST): $(OBJS)
- $(LINK) $(OBJS) to $(DEST) LIB $(LIBS) WITH $(DEST).lnk MAP $(DEST).map $(LNMAP)
- SHAR_EOF
- # End of shell archive
- exit 0
- --
- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
- Have five nice days.
-